home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / PCI Driver Sample / NCR_DriverProject / Src / DriverPrepMemoryInit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-08  |  7.6 KB  |  197 lines  |  [TEXT/MPCC]

  1. /*                                DriverPrepMemoryInit.c                                */
  2. /*
  3.  * DriverPrepMemoryInit.c
  4.  * Copyright © 1994-95 Apple Computer Inc. All rights reserved.
  5.  *
  6.  * .
  7.  */
  8. /*    .___________________________________________________________________________________.
  9.       | Initialize the permanent memory areas that are shared between the driver and the    |
  10.       | NCR card: the SCSI script and the per-request record. If this is extended to        |
  11.       | support concurrent I/O (i.e. to support SCSI suspend/resume), we must create and    |
  12.       | prepare several per-request records. When an application calls PBRead or PBWrite,    |
  13.       | a separate, more complex, function will handle preparation of the actual I/O        |
  14.       | buffer.
  15.     .___________________________________________________________________________________.
  16. */
  17. #include "NCRDriverPrivate.h"
  18.  
  19. /*
  20.  * Create an I/O Preparation table for the global script. This is created once, when
  21.  * the driver starts. The NCR chip reads the script asynchronously. This function
  22.  * may serve as an example for a general global shared area.
  23.  */
  24. OSErr
  25. PrepareMemoryForScript(
  26.         AddressSpaceID            addressSpaceID
  27.     )
  28. {
  29.         OSErr                    status;
  30.         ItemCount                mapEntriesNeeded;
  31.  
  32.         Trace(PrepareMemoryForScript);
  33.         GLOBAL.scriptIOTable.options =
  34.                     ( (0 * kIOIsInput)                    /* Chip won't write script    */
  35.                     | (1 * kIOIsOutput)                    /* Chip reads the script    */
  36.                     | (0 * kIOMultipleRanges)            /* No scatter-gather list    */
  37.                     | (1 * kIOLogicalRanges)            /* Logical addresses        */
  38.                     | (0 * kIOMinimalLogicalMapping)    /* Normal logical mapping    */
  39.                     | (1 * kIOShareMappingTables)        /* Share with Kernel        */
  40.                     | (0 * kIOCoherentDataPath)            /* No fancy data path        */
  41.                     );
  42.         GLOBAL.scriptIOTable.addressSpace = addressSpaceID;
  43.         GLOBAL.scriptIOTable.firstPrepared = 0;
  44.         GLOBAL.scriptIOTable.logicalMapping = NULL;
  45.         GLOBAL.scriptIOTable.rangeInfo.range.base = (LogicalAddress) gNCRSCSIScript;
  46.         GLOBAL.scriptIOTable.rangeInfo.range.length = gNCRSCSIScriptSize;
  47.         mapEntriesNeeded = GetMapEntryCount(gNCRSCSIScript, gNCRSCSIScriptSize);
  48.         GLOBAL.scriptIOTable.mappingEntryCount = mapEntriesNeeded;
  49.         GLOBAL.scriptIOTable.physicalMapping = PoolAllocateResident(
  50.                     mapEntriesNeeded * sizeof (PhysicalAddress),
  51.                     TRUE
  52.                 );
  53.         status = (GLOBAL.scriptIOTable.physicalMapping != NULL) ? noErr : memFullErr;
  54.         CheckStatus(status, "\pAllocate Script PhysicalMapping");
  55.         if (status == noErr) {
  56.             status = PrepareMemoryForIO(&GLOBAL.scriptIOTable);
  57.             CheckStatus(status, "\pPrepareMemory for Script");
  58.         }
  59.         if (status == noErr)
  60.             status = CheckForContiguousPhysicalMapping(&GLOBAL.scriptIOTable);
  61.         if (status != noErr)
  62.             PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
  63.         return (status);
  64. }
  65.  
  66. /*
  67.  * Dispose of the script I/O preparation table. This is called when the driver stops.
  68.  */
  69. void
  70. DisposeMemoryForScript(void)
  71. {
  72.         Trace(DisposeMemoryForScript);
  73.         CheckpointIOTable(&GLOBAL.scriptIOTable);
  74.         if (GLOBAL.scriptIOTable.physicalMapping != NULL)
  75.             (void) PoolDeallocate(GLOBAL.scriptIOTable.physicalMapping);
  76.         CLEAR(GLOBAL.scriptIOTable);
  77. }
  78.  
  79. /*
  80.  * Create a PerRequest record and its I/O Preparation table. To create the table, we
  81.  * must first determine the number of physical mapping table entries we will need for
  82.  * the user I/O request and the PerRequestRecord itself.
  83.  *
  84.  * This is called when the driver starts. If we support concurrent I/O, we create
  85.  * several of these records. The per-request record is a small amount of memory that
  86.  * is shared between the NCR card and the driver.
  87.  */
  88. OSErr
  89. CreatePerRequestRecord(
  90.         AddressSpaceID            addressSpaceID
  91.     )
  92. {
  93.         OSErr                    status;
  94.         OSStatus                osStatus;
  95.         PerRequestDataPtr        perRequestDataPtr;
  96.         ItemCount                requestMapEntries;        /* PerRequestData only        */
  97.         ByteCount                mapTableSize;
  98. #define REQUEST    (*perRequestDataPtr)
  99.  
  100.         Trace(CreatePerRequestRecord);
  101.         perRequestDataPtr = (PerRequestDataPtr)
  102.                     MemAllocatePhysicallyContiguous(sizeof (PerRequestData), TRUE);
  103.         status = (perRequestDataPtr != NULL) ? noErr : memFullErr;
  104.         CheckStatus(status, "\pAllocate PerRequestRecord");
  105.         if (status == noErr) {
  106.             /*
  107.              * PrepareNextDMATransfer will be called (as a Software Task) to prepare
  108.              * a subsequent "chunk" of DMA if the original preparation is incomplete.
  109.              */
  110.             osStatus = CreateSoftwareInterrupt(
  111.                         PrepareNextDMATask,                /* Handler function            */
  112.                         CurrentTaskID(),                /* For my driver task        */
  113.                         perRequestDataPtr,                /* Handler parameter        */
  114.                         TRUE,                            /* Persistant                */
  115.                         &REQUEST.nextDMAInterruptID        /* Result                    */
  116.                     );
  117.             CheckStatus(osStatus, "\pCreateSoftwareInterrupt");
  118.         }
  119.         if (status == noErr) {        
  120.             GLOBAL.perRequestDataPtr = perRequestDataPtr;
  121.             /*
  122.              * Allocate a maximum-length physical mapping table that will be used for
  123.              * each user I/O request. By passing a dummy value that happens to fall
  124.              * at the end of the page, we'll get the as many entries as we need.
  125.              */
  126.             REQUEST.scsiMapEntries = GetMapEntryCount(
  127.                         (void *) (GLOBAL.pageSize - 1), kNCRDriverMaxTransfer);
  128.             requestMapEntries = GetMapEntryCount(perRequestDataPtr, sizeof (PerRequestData));
  129.             mapTableSize = (REQUEST.scsiMapEntries + requestMapEntries)
  130.                         * sizeof (PhysicalAddress);
  131.             REQUEST.physicalMapTables = PoolAllocateResident(mapTableSize, TRUE);
  132.             /*
  133.              * Initialize the constant part of the PerRequest mapping table. We leave
  134.              * this prepared "forever" for now. In the future, we may checkpoint it
  135.              * so it is only prepared while an I/O request is active.
  136.              */
  137.             REQUEST.perRequestIOTable.options =
  138.                     ( (0 * kIOIsInput)                    /* These will be set by        */
  139.                     | (0 * kIOIsOutput)                    /* calling CheckpointIO        */
  140.                     | (0 * kIOMultipleRanges)            /* No scatter-gather list    */
  141.                     | (1 * kIOLogicalRanges)            /* Logical addresses        */
  142.                     | (0 * kIOMinimalLogicalMapping)    /* Normal logical mapping    */
  143.                     | (1 * kIOShareMappingTables)        /* Share with Kernel        */
  144.                     | (0 * kIOCoherentDataPath)            /* No fancy data path        */
  145.                     );
  146.             REQUEST.perRequestIOTable.addressSpace = addressSpaceID;
  147.             REQUEST.perRequestIOTable.firstPrepared = 0;
  148.             REQUEST.perRequestIOTable.logicalMapping = NULL;
  149.             REQUEST.perRequestIOTable.rangeInfo.range.base = perRequestDataPtr;
  150.             REQUEST.perRequestIOTable.rangeInfo.range.length = sizeof (PerRequestData);
  151.             REQUEST.perRequestIOTable.physicalMapping =
  152.                         &REQUEST.physicalMapTables[REQUEST.scsiMapEntries];
  153.             REQUEST.perRequestIOTable.mappingEntryCount = requestMapEntries;
  154.             /*
  155.              * Note that the PerRequestData record is prepared once, and checkpointed
  156.              * before and after each transaction -- kMoreTransfers will be used so
  157.              * that system resources are not released.
  158.              */
  159.             status = PrepareMemoryForIO(&REQUEST.perRequestIOTable);
  160.             CheckStatus(status, "\pPrepareMemoryForIO perRequest");
  161.         }
  162.         if (status != noErr)
  163.             DisposePerRequestRecord(&GLOBAL.perRequestDataPtr);
  164.         if (status != noErr)
  165.             PublishInitFailureMsg(status, "\pPrepareMemoryForScript failed");
  166.         return (status);
  167. #undef REQUEST
  168. }
  169.  
  170. /*
  171.  * This is called when the driver is finalized.
  172.  */
  173. void
  174. DisposePerRequestRecord(
  175.         PerRequestDataPtr        *perRequestPtrAddr
  176.     )
  177. {
  178.         PerRequestDataPtr        perRequestDataPtr;
  179. #define REQUEST    (*perRequestDataPtr)
  180.  
  181.         Trace(DisposePerRequestRecord);
  182.         while ((perRequestDataPtr = *perRequestPtrAddr) != NULL) {
  183.             if (CompareAndSwap(
  184.                 (UInt32) perRequestDataPtr, NULL, (UInt32 *) perRequestPtrAddr)) {
  185.                 CheckpointIOTable(&REQUEST.scsiIOTable);
  186.                 CheckpointIOTable(&REQUEST.perRequestIOTable);
  187.                 if (REQUEST.nextDMAInterruptID != kInvalidID)
  188.                     (void) DeleteSoftwareInterrupt(REQUEST.nextDMAInterruptID);
  189.                 if (REQUEST.physicalMapTables != NULL)
  190.                     (void) PoolDeallocate(REQUEST.physicalMapTables);
  191.                 (void) PoolDeallocate(perRequestDataPtr);
  192.             }
  193.         }
  194. #undef REQUEST
  195. }
  196.  
  197.